﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace Worms3003
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region atributos
        #region enum de estados
        public enum Estados
        {
            introducao,
            jogo,
            creditos
        }
        #endregion
        public static GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Estados estados;
        States introducao;
        States jogo;
        States creditos;
        States jogo2;
        Worms worm1;
        Worms worm2;
        Birds bird;
        List<Birds> bird_list = new List<Birds>();
        public static KeyboardState oldkeystate;
        Sounds sons;
        SoundEffect aguia2;
        bool pause = false;
        int verificador = 0;
        Aim mira;
        Weapons bullet;
        Weapons bazooka;
        Random randomico = new Random();
        Vector2 direction, direction2;
        int timer;
        bool rodada1 = true;
        int verificador_rodada = 0;


        #region colisão por pixels
        Color[] worm2_mapa_de_cores;
        Color[] worm_mapa_de_cores;
        Color[] cenario_mapa_de_cores;


        #endregion


        int posicaoy;

        #endregion

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            estados = Estados.introducao;
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {

            #region construtor da classe
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            introducao = new States(Content.Load<Texture2D>("Worms2"), new Vector2(0f, 0f), 800, 600,
                                    Content.Load<SpriteFont>("Verdana"), "introducao", new Vector2(0f, 0f), Color.Red);
            jogo = new States(Content.Load<Texture2D>("Cars2"), new Vector2(0f, 0f), 1280, 640,
                              Content.Load<SpriteFont>("Verdana"), "jogo", new Vector2(500f, 0f), Color.White);
            jogo2 = new States(Content.Load<Texture2D>("montanhas"), new Vector2(0f, 70f), 1280, 960, Color.White);
            creditos = new States(Content.Load<Texture2D>("worms3"), new Vector2(0f, 0f), 800, 600,
                                  Content.Load<SpriteFont>("Verdana"), "creditos", new Vector2(0f, 0f), Color.Blue);
            sons = new Sounds(Content.Load<Song>("music"));
            aguia2 = Content.Load<SoundEffect>("aguia2");
            worm1 = new Worms(Content.Load<Texture2D>("teste3"), 36, 39, 0, 0, 36, 39, 0, 0, 20, 1, 2, 0f, new Vector2(5f, 5f), SpriteEffects.FlipHorizontally, Color.White);
            worm1.positions = new Vector2(150, 0);
            worm1.barra_de_vida = Content.Load<Texture2D>("barradeenergia1");
            worm1.cor_barra_de_vida = Color.Red;
            // Que porra é essa ? Alex explica pq tem largura e altura 1.000 vezes ? Toh fazendo as animações XD
            worm2 = new Worms(Content.Load<Texture2D>("wutllnk"), 70, 70, 0, 512, 60, 57, 0, 57, 20, 0, 6, 0f, new Vector2(5f, 5f), SpriteEffects.FlipHorizontally, Color.White);
            
           // worm2 = new Worms(Content.Load<Texture2D>("wutllnk"), 70, 70, 0, 512, 60, 57, 0, 57, 20, 0, 6, 0f, new Vector2(5f, 5f), SpriteEffects.FlipHorizontally, Color.White);
            worm2.positions = new Vector2(500, 0);
            worm2.barra_de_vida = Content.Load<Texture2D>("barradeenergia1");
            worm2.cor_barra_de_vida = Color.Blue;
            mira = new Aim(Content.Load<Texture2D>("alvo"), Vector2.Zero);
            bullet = new Weapons(Content.Load<Texture2D>("bazooka"), new Vector2((worm1.positions.X + 40f), (worm1.positions.Y + 35f)), SpriteEffects.None);
            bazooka = new Weapons(Content.Load<Texture2D>("bazooka"), new Vector2((worm2.positions.X + 40f), (worm2.positions.Y + 35f)), SpriteEffects.None);
            #endregion

            #region Colisão por pixels

            worm2_mapa_de_cores = new Color[worm2.textura.Width * worm2.textura.Height];
            worm2.textura.GetData(worm2_mapa_de_cores);

            worm_mapa_de_cores = new Color[worm1.textura.Width * worm1.textura.Height];
            worm1.textura.GetData(worm_mapa_de_cores);

            cenario_mapa_de_cores = new Color[jogo.texturas.Width * jogo.texturas.Height];
            jogo.textura.GetData(cenario_mapa_de_cores);

            #endregion

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            KeyboardState keyboard = Keyboard.GetState();

            if (keyboard.IsKeyDown(Keys.K))
            {
                aguia2.Play();
            }

             #region pause
            if (keyboard.IsKeyDown(Keys.Pause) && !oldkeystate.IsKeyDown(Keys.Pause))
            {
                verificador++;

                if(verificador % 2 == 0)
                    pause = false;

                else
                    pause = true;
            }
            #endregion

            if (!pause)
            {
                switch (estados)
                {
                    #region introducao
                    case Estados.introducao:
                        {
                            sons.Update();

                            if (keyboard.IsKeyDown(Keys.Enter) && !oldkeystate.IsKeyDown(Keys.Enter))
                            {
                                estados = Estados.jogo;
                                MediaPlayer.Pause();
                            }

                            break;
                        }
                    #endregion

                    #region jogo
                    case Estados.jogo:
                        {
                            #region colisão por pixel
                          
                            Rectangle worm_retangulo = new Rectangle((int)(worm1.posicao.X + jogo.posicao.X), (int)(worm1.posicao.Y + jogo.posicao.Y), worm1.largura, worm1.altura);

                            Rectangle worm2_retangulo = new Rectangle((int)(worm2.posicao.X + jogo.posicao.X), (int)(worm2.posicao.Y + jogo.posicao.Y), worm2.largura, worm2.altura);

                            Rectangle cenario_retangulo = new Rectangle(0,0, jogo.textura.Width, jogo.textura.Height);

                            if(Colisao_Pixel(worm2_retangulo, worm2_mapa_de_cores, cenario_retangulo, cenario_mapa_de_cores))
                            {
                                worm2.gravidade.Y = 0;
                                worm2.esperar = false;

                                if(worm2.estados == Worms.Estados.andando)
                                    worm2.posicao.Y=posicaoy;
                            }

                            else
                            {
                                worm2.gravidade.Y = 2f;
                            }

                            if (Colisao_Pixel(worm_retangulo, worm_mapa_de_cores, cenario_retangulo, cenario_mapa_de_cores))
                            {
                                worm1.gravidade.Y = 0;
                                worm1.esperar = false;
                                if (worm1.estados == Worms.Estados.andando)
                                    worm1.posicao.Y = posicaoy;

                            }
                            else
                            {
                                worm1.gravidade.Y = 2f;
                            }

                            #endregion

                            timer += gameTime.ElapsedGameTime.Milliseconds;
                            MouseState mouse = Mouse.GetState();

                            mira.Update();
                            bullet.vetor = new Vector2(worm1.posicao.X + 20f, worm1.posicao.Y + 20f);
                            bazooka.vetor = new Vector2(worm2.posicao.X + 40f, worm2.posicao.Y + 40f);


                            /*
                            bullet.Update();
                            bazooka.Update();
                             */

                            #region angulo da rotação da mira e das armas
                            direction = bullet.vector - mira.Position;
                            //foreach  (Weapons b in listaweapns)
                            //b.direction2 = bazooka.vector - mira.Position;
                            direction2 = bazooka.vector - mira.Position;
                            bullet.rotacao = (float)(Math.Atan2(direction.Y, direction.X));
                            bazooka.rotacao = (float)(Math.Atan2(direction2.Y, direction2.X));
                            #endregion

                            #region passaros
                            for (int i = 0; i < bird_list.Count; i++)
                            {
                                bird_list[i].Update(gameTime);
                                bird_list[i].posicao.X += 5f;
                            }

                            if (timer >= 2000)
                            {
                                //carrega as texturas de dois em dois segundos
                                bird = new Birds(Content.Load<Texture2D>("birds"), 60, 57, 0, 0, 60, 57, 0, 58, 100, 0, 14, 0f, new Vector2(0f, 0f), SpriteEffects.None, Color.White);
                                bird.positions = new Vector2(0, randomico.Next(0, 220));
                                bird_list.Add(bird);
                                timer = 0;
                            }

                            #endregion

                            //rever de acordo com as novas animações
                            #region worm

                            #region rodada de cada worm
                            if (!worm1.esperar && !worm2.esperar)
                            {
                                if (keyboard.IsKeyDown(Keys.Enter) && !oldkeystate.IsKeyDown(Keys.Enter))
                                {
                                    verificador_rodada++;

                                    if (verificador_rodada % 2 == 0)
                                        rodada1 = true;
                                    else
                                        rodada1 = false;
                                }

                                if (rodada1)
                                    worm1.Update(gameTime);
                                else
                                    worm2.Update(gameTime);
                            }

                            else
                            {
                                worm1.Update(gameTime);
                                worm2.Update(gameTime);
                            }
                            #endregion

                            //apagar depois de fazermos o novo
                            #region jogo antigo
                            // worm2.bazooka.Y = bazooka.vetor.Y;
                            //fazer uma classe filho só para o worm, fazer os estados do worms, tiro, colisão por pixel

                         /*   if (keyboard.IsKeyDown(Keys.Up))
                            {
                                //estado olhando para cima
                                if(worm1.frameY != worm1.totalFramesY)
                                    worm1.Update(gameTime);
                            }*/

                            /*       if (keyboard.IsKeyDown(Keys.Down))
                                   {
                                       if (!(worm1.frameY != worm1.totalFramesY))
                                       {
                                           if (worm1frameY > 0)
                                               worm1.frameY = 0;
                                       }

                                   }

                                   if (keyboard.IsKeyDown(Keys.Right))
                                   {
                                       worm1.vetor.X += 5f;
                                       worm1.spriteEffects = SpriteEffects.FlipHorizontally;
                                       worm1.bazooka.X += 5f;
                                       bullet.vetor.X += 5f;
                                       worm1.x = 57;
                                       worm1.y = 0;
                                       worm1.Update(gameTime);
                                   }

                                   if (keyboard.IsKeyDown(Keys.Left))
                                   {
                                       worm1.vetor.X -= 5f;
                                       worm1.spriteEffects = SpriteEffects.None;
                                       bullet.vetor.X -= 5f;
                                       worm1.x = 57;
                                       worm2.y = 0;
                                       worm1.Update(gameTime);
                                   }

                              /*     if (keyboard.IsKeyDown(Keys.Space))
                                   {
                                       worm2.x = 115;
                                       worm2.y = 0;
                                       worm2.totalFramesY = 11;
                                       worm2.Pulando(gameTime);
                                   }

                                   if (keyboard.IsKeyUp(Keys.Space))
                                   {
                                       worm2.pulando = false;
                                       worm2.vetor.Y = (bazooka.vetor.Y - 45);
                                   }*/
                            #endregion

                            #endregion

                            #region scroll e paralaxe
                            if (mouse.X + 5 >= GraphicsDevice.Viewport.Width &&
                               (jogo.vector.X <= jogo.texturas.Width - GraphicsDevice.Viewport.Width))
                            {
                                jogo.posicao.X += 4f;
                                worm1.posicao.X -= 4f;
                                worm2.posicao.X -= 4f;
                                bullet.vetor.X -= 4f;
                                bazooka.vetor.X -= 4f;

                                for (int i = 0; i < bird_list.Count; i++)
                                {
                                    bird_list[i].posicao.X -= 4f;
                                }

                                jogo2.posicao.X += 4 * 0.25f;
                            }

                            if (mouse.X + 5 <= 0 && jogo.vector.X >= 0)
                            {
                                jogo.posicao.X -= 4f;
                                worm1.posicao.X += 4f;
                                worm2.posicao.X += 4f;

                                for (int i = 0; i < bird_list.Count; i++)
                                {
                                    bird_list[i].posicao.X += 4f;
                                }

                                bullet.vetor.X += 4;
                                bazooka.vetor.X += 4f;
                               jogo2.posicao.X -= 4 * 0.25f;
                            }

                            if (mouse.Y + 5 <= 0 && jogo.vector.Y >= 0)
                            {
                                worm1.posicao.Y += 4f;
                                worm2.posicao.Y += 4f;
                                jogo.posicao.Y -= 4f;
                                

                                for (int i = 0; i < bird_list.Count; i++)
                                {
                                    bird_list[i].posicao.Y += 4f;
                                }

                                bullet.vetor.Y += 4f;
                                bazooka.vetor.Y += 4f;
                                jogo2.posicao.Y -= 4 * 0.25f;
                            }

                            if (mouse.Y + 5 >= GraphicsDevice.Viewport.Height &&
                               (jogo.vector.Y <= jogo.texturas.Height - GraphicsDevice.Viewport.Height))
                            {

                                worm1.posicao.Y -= 4f;
                                worm2.posicao.Y -= 4f;
                                jogo.posicao.Y += 4f;

                                for (int i = 0; i < bird_list.Count; i++)
                                {
                                    bird_list[i].posicao.Y -= 4f;
                                }

                                bullet.vetor.Y -= 4f;
                                bazooka.vetor.Y -= 4f;
                                jogo2.posicao.Y += 4 * 0.25f;
                            }
                            #endregion

                            if (keyboard.IsKeyDown(Keys.Enter) && !oldkeystate.IsKeyDown(Keys.Enter))
                                estados = Estados.creditos;

                            break;
                        }
                    #endregion

                    #region creditos
                    case Estados.creditos:
                        {
                            if (keyboard.IsKeyDown(Keys.Enter) && !oldkeystate.IsKeyDown(Keys.Enter))
                            {
                                estados = Estados.introducao;
                                MediaPlayer.Resume();
                            }

                            break;
                        }
                    #endregion
                }
            }

            oldkeystate = keyboard;

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            spriteBatch.Begin();

            switch (estados)
            {
                #region estados
                case Estados.introducao: introducao.Draw(spriteBatch); break;

                case Estados.jogo: jogo2.DrawScroll(spriteBatch); 
                                   jogo.DrawScrollwithFont(spriteBatch); 
                                   worm1.Draw(spriteBatch);
                                   worm2.Draw(spriteBatch);
                                   foreach (Birds i in bird_list)
                                   {
                                       i.Draw(spriteBatch);
                                   }
                                   mira.Draw(spriteBatch); 
                                   bullet.Draw(spriteBatch);
                                   bazooka.Draw(spriteBatch);
                                   //spriteBatch.DrawString(introducao.fonte, "PosX: " + Mouse.GetState().X + "\nPosY: " + Mouse.GetState().Y, new Vector2(0, 0), Color.Red);
                                  // spriteBatch.DrawString(introducao.fonte, "Angulo: " + bullet.rotacao , new Vector2(0, 80), Color.Red);
                                  break;

                case Estados.creditos: creditos.Draw(spriteBatch); break;
                #endregion
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }



        #region criando a função da colisão por pixel
        public bool Colisao_Pixel(Rectangle retanguloA, Color[] mapa_de_coresA, Rectangle retanguloB, Color[] mapa_de_coresB)
        {
            int cima = Math.Max(retanguloA.Top, retanguloB.Top);
            int baixo = Math.Min(retanguloA.Bottom, retanguloB.Bottom);
            int esquerda = Math.Max(retanguloA.Left, retanguloB.Left);
            int direita = Math.Min(retanguloA.Right, retanguloB.Right);


            for (int y = cima; y < baixo; y++)
            {
                for (int x = esquerda; x < direita; x++)
                {
                    Color corA = mapa_de_coresA[(x - retanguloA.Left) + (y - retanguloA.Top) * retanguloA.Width];
                    Color corB = mapa_de_coresB[(x - retanguloB.Left) + (y - retanguloB.Top) * retanguloB.Width];
                    if (corA.A != 0 && corB.A != 0)
                    {
                        posicaoy = y - worm2.altura;
                        return true;
                    }


                }

            }


            return false;
        }

        #endregion


    }
}
